package com.zdsx.config;

import lombok.Getter;
import org.springframework.util.StreamUtils;
import org.springframework.web.util.ContentCachingRequestWrapper;

import javax.servlet.ServletInputStream;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.Map;

@Getter
public class LogRequest extends JsonPayload {
    private final String method;
    private final String remoteAddr;
    private final String requestURI;
    private final Map<String, String> parameters;

    private static final byte[] EMPTY = new byte[0];

    public LogRequest(ContentCachingRequestWrapper request) {
        super(getPayload(request, request.getCharacterEncoding(), request.getContentType()), getHeaders(request));
        this.method = request.getMethod();
        this.remoteAddr = request.getRemoteAddr();
        this.requestURI = request.getRequestURI();
        this.parameters = getRequestParam(request);
    }

    public static Map<String, String> getHeaders(ContentCachingRequestWrapper request) {
        LinkedHashMap<String, String> singleValueMap = new LinkedHashMap<>();
        for (Enumeration<String> names = request.getHeaderNames(); names.hasMoreElements(); ) {
            String headerName = names.nextElement();
            singleValueMap.put(headerName, request.getHeader(headerName));
        }
        return singleValueMap;
    }

    private static Map<String, String> getRequestParam(ContentCachingRequestWrapper request) {
        Map<String, String[]> parameters = request.getParameterMap();
        LinkedHashMap<String, String> singleValueMap = new LinkedHashMap<>(parameters.size());
        parameters.forEach((key, valueList) -> singleValueMap.put(key, valueList == null ? null : valueList[0]));
        return singleValueMap;
    }

    private static String getPayload(ContentCachingRequestWrapper request, String characterEncoding, String contentType) {
        if (!isJson(contentType)) {
            return null;
        }
        return toString(getPayload(request), characterEncoding);
    }

    private static byte[] getPayload(ContentCachingRequestWrapper request) {
        try {
            ServletInputStream is = request.getRequest().getInputStream();
            byte[] rawData;
            if (is.isFinished()) {
                rawData = request.getContentAsByteArray();
            } else {
                rawData = StreamUtils.copyToByteArray(request.getInputStream());
            }
            return JsonStringBuilder.compress(rawData);
        } catch (Exception e) {
            return EMPTY;
        }
    }
}
